const canvas = document.getElementById('canvas')
const ctx =canvas.getContext('2d')
const points = []


const drawAxis = (ctx,config) => {               //绘制坐标轴
    ctx.save()
    const {origin, xAxis, yAxis} = config
    ctx.linewidth = 1
    ctx.strokeStyle = 'orange'
    ctx.beginPath()

    const xAxisHeight = 5                       //绘制刻度
    const yAxisWidht = 5

    ctx.moveTo(origin.x, origin.y)
    ctx.lineTo(origin.x + xAxis.length, origin.y)
    for (let i = 0; i< xAxis.length / xAxis.gap; i++) {
      const { gap } = xAxis
      ctx.moveTo(origin.x + gap * i, origin.y - xAxisHeight)
      ctx.lineTo(origin.x + gap * i, origin.y)
    }
    for (let i = 0; i< yAxis.length / yAxis.gap; i++){
      const { gap } = yAxis
      ctx.moveTo(origin.x + yAxisWidht, origin.y - gap * i)
      ctx.lineTo(origin.x , origin.y - gap * i)
    }
    
    ctx.moveTo(origin.x, origin.y)
    ctx.lineTo(origin.x, origin.y - yAxis.length)

    ctx.moveTo(origin.x + xAxis.length, origin.y)                 //绘制箭头
    ctx.lineTo(origin.x + xAxis.length - 5, origin.y - 2)
    ctx.moveTo(origin.x + xAxis.length, origin.y)
    ctx.lineTo(origin.x + xAxis.length - 5, origin.y + 2)

    ctx.moveTo(origin.x, origin.y + yAxis.length)
    ctx.lineTo(origin.x + 2, origin.y - yAxis.length + 5)
    ctx.moveTo(origin.x, origin.y + yAxis.length)
    ctx.lineTo(origin.x - 2, origin.y - yAxis.length + 5)

    ctx.stroke()
    ctx.closePath()
    ctx.restore()
}

const drawPoint = (ctx, cx, cy, r) => {                        //绘制圆
  ctx.save()
  ctx.linewidth = 1
  ctx.moveTo(cx, cy)
  ctx.beginPath()
  ctx.arc(cx, cy, r, 0, Math.PI * 2)
  ctx.fillStyle = '#ffffff'
  ctx.fill()
  ctx.strokeStyle = 'blue'
  ctx.stroke()
  ctx.closePath()
  ctx.restore()
}

const drawPoints = (ctx, points) => {
  points.forEach(p => {
    drawPoint(ctx, p.x, p.y, p.r)
  })
}

const drawLine = (ctx, p1,p2) => {                   //画线，传入画笔，p1,p2
  ctx.save()                                         //保存
  ctx.beginPath()                                    //开始
  ctx.moveTo(p1.x, p1.y)
  ctx.lineTo(p2.x, p2.y)                             //从p1到p2  
  ctx.stroke()                                       //描边
  ctx.closePath()
  ctx.restore()                                      //返回
}

const drawLines = (ctx, points) => {
  if (points.length < 2) {
    return 
  }
  ctx.save()
  ctx.beginPath()
  ctx.moveTo(points[0].x, points[0].y)
  for (let i = 1; i < points.length; i++) {
    ctx.lineTo(points[i].x, points[i].y)
  }
  ctx.stroke()
  ctx.closePath()
  ctx.restore()
}

const drawSmoothLines = (ctx, points) => {
  if (points.length < 3) {
    drawLines(ctx, points)
    return
  }
  const f = 0.3                  //做一个基本配置，准备两个系数,改变曲线的效果，控制曲线的平滑和弯曲的效果
  const t = 0.6
  const gradient = (a,b) => (b.y - a.y)  / (b.x - a.x)     //增加一个方法，计算两个点的梯度,获得a,b两点斜率
  ctx.save()

  ctx.beginPath()
  ctx.moveTo(points[0].x, points[0].y)                    //移到第一个点
  let g = 0
  let dx1 = 0
  let dy1 = 0                                             //第一个点的偏移
  let dx2 = 0
  let dy2 = 0                                             //第二个点的偏移
  let prePoint = points[0]
  let nextPoint = null
  for (let i = 1; i < points.length; i++) {              //进入循环计算
    let curPoint = points[i]
    nextPoint = points[i+1]
    if (nextPoint) {                                     //把nextPoint包一下，控制i走到位置，不然会走到null
      g = gradient(prePoint, nextPoint)                  //计算前一个点和后一个点的斜率关系
      dx2 = (nextPoint.x - curPoint.x) * (-f)
      dy = dx2 * g * t
    }else {
      dx2 = 0
      dy2 = 0
    }
    ctx.bezierCurveTo(prePoint.x - dx1, prePoint.y - dy1, curPoint.x + dx2, curPoint.y + dy2, curPoint.x, curPoint.y)
    //贝塞尔曲线方法，控制点1的位置
    dx1 = dx2
    dy1 = dy2
    prePoint =curPoint
  }
  ctx.stroke()
  ctx.closePath()

  ctx.restore()
}


const canvasInit = () => {                              //画布重绘
  ctx.clearRect(0, 0, canvas.width, canvas.height)      //清空画布，清空一个矩形区域
  drawAxis(ctx, {
    origin: {
      x: 1,
      y: 220 
    },
    xAxis: {
      length: 400,
      gap: 10
    },
    yAxis: {
      length: 200,
      gap: 10
    }
  })                                    //轴重绘
  drawSmoothLines(ctx,points)
  drawPoints(ctx, points)
}                                      //点重绘

canvasInit()
//不能让其重复绘制，重复绘制说明之前的画布还没有清空，就画上去覆盖了
//因为canvas不会记录之前所画过的东西

canvas.addEventListener('click', e => {
  const clickPosition = {
    x: e.clientX,
    y: e.clientY
  }
  const { left, top } =canvas.getBoundingClientRect()
  const canvasOffset = {
    x: left,
    y: top
  }
  points.push({                                   //记录一下点的位置
    x: clickPosition.x -canvasOffset.x,
    y: clickPosition.y -canvasOffset.y,
    r: 5
  })
  canvasInit()
})

canvas.addEventListener('mousemove', e => {
  const inCircle = (p, cx, cy, r) =>{                                    //判断鼠标在点附近，incircle方法判断距离
    const distance = Math.sqrt((p.x - cx) ** 2 + (p.y - cy) ** 2)        //求距离，距离公式
    if (distance <= r) {                                                 //判断是否小于半径
      return true
    }
    return false
  }
  const mousePosition = {
    x: e.clientX,
    y: e.clientY
  }
  const { left, top } = canvas.getBoundingClientRect()
  const canvasoffset = {
    x: left,
    y: top
  }
  const canvasPosition = {                                             //canvas的偏移
    x: mousePosition.x - canvasoffset.x,
    y: mousePosition.y - canvasoffset.y
  }
  let repaintFlag = false
  for (let i = 0; i < points.length; i++) {                           //对所有的点进行遍历查询
    const ifInCircle = inCircle(canvasPosition, points[i].x, points[i].y,points[i].r)
    if (ifInCircle) {                                                 //直接调用incircle方法
      points[i].r = 8 
      canvas.style.cursor = 'pointer'                     //加个样式使鼠标变成手的样子，进入的时候变成pointer
      repaintFlag = true
      break
    } else if (!ifInCircle && points[i].r !==5) {         //如果不在圆内，且半径不等于5，也需要重绘
      points[i].r = 5
      canvas.style.cursor = ''                            //离开的时候滞空，变成自动
      repaintFlag = true
      break
    }    
  }
  if (repaintFlag) {                          //如果需要重绘
    canvasInit()
  }
})


let x = 10                                      //坐标轴的问题   

//setInterval(() => {                          //一个定时器自动生成，一秒一个
//  const randomY = 220 - Math.random() * 100  //0到100的随机数
//  points.push({                              
//    x: x,
//    y: randomY,
//    r: 5
//  })                                         //点里面push 
//  x += 15                                    //x间隔15
//  canvasInit()                               //进行重绘
//}, 1000)

